package edu.scau.divineplace.service;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import edu.scau.divineplace.entity.constant.ScoreConstants;
import edu.scau.divineplace.entity.enums.LikeTargetTypeEnum;
import edu.scau.divineplace.entity.query.PageQuery;
import edu.scau.divineplace.entity.vo.commentscore.CommentScoreTotalVO;
import edu.scau.divineplace.entity.dos.CommentScoreDO;
import edu.scau.divineplace.entity.dos.UserDO;
import edu.scau.divineplace.entity.vo.commentscore.CommentScoreGroupVO;
import edu.scau.divineplace.entity.vo.commentscore.CommentScoreVO;
import edu.scau.divineplace.entity.vo.commentscore.ContentScoreVO;
import edu.scau.divineplace.util.BeanConvertUtils;
import edu.scau.divineplace.util.PageQueryUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @Author: x1aolone
 * @Date: 2020/12/11 15:48
 */
@Service
public class CommentScoreService {

    @Autowired
    private ImportMapperService importMapperService;

    @Autowired
    private LikeService likeService;


    /**
     * 通过内容id获取评分列表，支持分页
     * @param contentId
     * @param userId
     * @param pageQuery
     * @return
     */
    public List<CommentScoreVO> list(Long contentId, Long userId, PageQuery pageQuery){
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        List<CommentScoreVO> VOS= Lists.newArrayList();
        Page<CommentScoreDO> commentScorePage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        LambdaQueryWrapper<CommentScoreDO> query = Wrappers.<CommentScoreDO>lambdaQuery()
                .eq(CommentScoreDO::getContentId, contentId)
                .orderByDesc(CommentScoreDO::getUpdateTime)
                .orderByDesc(CommentScoreDO::getCreateTime);
        commentScorePage = importMapperService.commentScoreMapper.selectPage(commentScorePage, query);
        for (CommentScoreDO DO : commentScorePage.getRecords()) {
            UserDO UDO = importMapperService.userMapper.selectById(DO.getUserId());
            Integer likeNum = likeService.count(LikeTargetTypeEnum.COMMENT_SCORE, DO.getId());
            Boolean isLiked = null;
            if (userId != null) {
                isLiked = likeService.judge(userId, DO.getId(), LikeTargetTypeEnum.COMMENT_SCORE.getType());
            }
            VOS.add(CommentScoreVO.builder()
                    .commentScore(DO)
                    .user(UDO)
                    .likeNum(likeNum)
                    .isLiked(isLiked)
                    .build()
            );
        }
        return VOS;
    }


    /**
     * 通过内容id获取评分列表
     * @param contentId
     * @return
     */
    public CommentScoreVO get(Long contentId, Long userId){
        LambdaQueryWrapper<CommentScoreDO> query = Wrappers.<CommentScoreDO>lambdaQuery()
                .eq(CommentScoreDO::getUserId, userId)
                .eq(CommentScoreDO::getContentId, contentId)
                .last("limit 1");
        CommentScoreDO DO = importMapperService.commentScoreMapper.selectOne(query);
        CommentScoreVO VO = CommentScoreVO.builder()
                .commentScore(DO)
                .build();
        return VO;
    }

    /**
     * 获取内容的评分，总评分 + 每类评分(1/2/3/4/5)的评分
     * @param contentId
     * @return
     */
    public ContentScoreVO getContentScore (Long contentId){
        // 获取总评
        CommentScoreTotalVO scoreTotalVO = getTotalScore(contentId);
        Double score = calcScore(scoreTotalVO.getTotalScore(), scoreTotalVO.getTotalScorePeople());
        // 获取每个评分的人数
        List<CommentScoreGroupVO> scoreGroup = getScoreGroup(contentId);
        ContentScoreVO VO = ContentScoreVO.builder()
                .score(score)
                .scoreGroup(scoreGroup)
                .build();
        return VO;
    }

    /**
     * 获取内容的每类评分(1/2/3/4/5)的打分人数
     * @param contentId 内容id
     * @return
     */
    public List<CommentScoreGroupVO> getScoreGroup (Long contentId){
        QueryWrapper<CommentScoreDO> query = Wrappers.<CommentScoreDO>query()
                .select("count(id) as num, score")
                .eq("content_id", contentId)
                .groupBy("score")
                .orderByDesc("score");
        List<Map<String, Object>> scoreMaps = importMapperService.commentScoreMapper.selectMaps(query);
        List<CommentScoreGroupVO> scoreVOS = BeanConvertUtils.Maps2Entities(scoreMaps, CommentScoreGroupVO.class);
        List<CommentScoreGroupVO> VOS = Lists.newArrayList();
        int index = 0;
        // 遍历VO, 如果评分缺失就填充
        for (int i = ScoreConstants.MAX; i >= ScoreConstants.MIN; i--) {
            CommentScoreGroupVO VO = null;
            if (index < scoreVOS.size()) {
                VO = scoreVOS.get(index);
            }
            if (VO != null && VO.getScore() == i) {
                VOS.add(VO);
                index++;
            } else {
                VOS.add(
                        CommentScoreGroupVO.builder()
                                .score(i)
                                .num((long) 0)
                                .build()
                );
            }
        }
        return VOS;
    }

    /**
     * 通过内容id获取内容评分信息，总评分和总打分人数
     * @param contentId
     * @return
     */
    public CommentScoreTotalVO getTotalScore (Long contentId){
        QueryWrapper<CommentScoreDO> query = Wrappers.<CommentScoreDO>query()
                .select("COUNT(id) as totalScorePeople, IFNULL(SUM(score), 0) as totalScore")
                .eq("content_id", contentId);
        List<Map<String, Object>> scoreMaps = importMapperService.commentScoreMapper.selectMaps(query);
        if (scoreMaps != null) {
            CommentScoreTotalVO VO = BeanConvertUtils.Map2Entity(scoreMaps.get(0), CommentScoreTotalVO.class);
            return VO;
        }
        return CommentScoreTotalVO.empty();
    }

    /**
     * 通过总评分、总评价人数，计算评分
     * @param totalScore
     * @param totalScorePeople
     * @return
     */
    public Double calcScore (Integer totalScore, Integer totalScorePeople){
        double score = 0;
        if (totalScorePeople != 0) {
            score = 2.0 * totalScore / totalScorePeople;
            score = NumberUtil.round(score, 1).doubleValue();
        }
        return score;
    }

    /**
     * 通过内容id、用户id、分数、评论，新增评论
     * @param contentId
     * @param userId
     * @param score
     * @param comment
     */
    public void add (Long contentId, Long userId, Integer score, String comment) {
        CommentScoreDO DO = new CommentScoreDO();
        DO.setContentId(contentId);
        DO.setUserId(userId);
        DO.setScore(score);
        DO.setComment(comment);
        importMapperService.commentScoreMapper.insert(DO);
    }

    /**
     * 通过内容id、用户id、分数、评论，修改评论
     * @param contentId
     * @param userId
     * @param score
     * @param comment
     */
    public void update (Long contentId, Long userId, Integer score, String comment) {
        LambdaUpdateWrapper<CommentScoreDO> updateWrapper = Wrappers.<CommentScoreDO>lambdaUpdate()
                .eq(CommentScoreDO::getContentId, contentId)
                .eq(CommentScoreDO::getUserId, userId)
                .set(CommentScoreDO::getScore, score)
                .set(CommentScoreDO::getComment, comment);
        // entity传null的时候，自动填充的updateTime不会填充进去，所以new一个
        importMapperService.commentScoreMapper.update(new CommentScoreDO(), updateWrapper);
    }

    /**
     * 通过评分id、分数、评论，修改评论
     * @param commentScoreId
     * @param score
     * @param comment
     */
    public void update (Long commentScoreId, Integer score, String comment) {
        LambdaUpdateWrapper<CommentScoreDO> updateWrapper = Wrappers.<CommentScoreDO>lambdaUpdate()
                .eq(CommentScoreDO::getId, commentScoreId)
                .set(CommentScoreDO::getScore, score)
                .set(CommentScoreDO::getComment, comment);
        // entity传null的时候，自动填充的updateTime不会填充进去，所以new一个
        importMapperService.commentScoreMapper.update(new CommentScoreDO(), updateWrapper);
    }


}
